
import wx

import ab_exceptions

import ab_plugins as ap

# Parameters
CfgparaHighSectMax = 0x01
CfgParaVerbose = 0x02
CfgParaLineLength = 0x03
CfgParaTreeMatchEnable = 0x04
CfgParaTreeAllMatches = 0x05
CfgParaTreeMatchMode = 0x06
CfgParaReloadBackground = 0x07
CfgParaReloadIndicator = 0x08
CfgParaColorFontHigh = 0x09
CfgParaColorBackHigh = 0x0a
CfgParaColorFontLabel = 0x0b
CfgParaColorBackLabel = 0x0c
CfgParaReloadSuppress = 0x0d
CfgParaBlockCacheSize = 0x0e
CfgParaTreeDispFormat = 0x0f
CfgParaFileLogName = 0x10
CfgParaFileRecentOpened = 0x12
CfgParaDisplayFont = 0x13
CfgParaDefaultRecNum = 0x14
CfgParaTreeColor = 0x15
CfgParaEnableTextMode = 0x16
CfgParaIgoreIntfError = 0x18
CfgParaAppRestart = 0x19
CfgParaAnaFileTop = 0x1a
CfgParaAnaFileLeft = 0x1b
CfgParaAnaFileWidth = 0x1c
CfgParaAnaFileHeight = 0x1d
CfgParaExtraPlx = 0x1e
CfgParaEnableAutoLine = 0x1f
CfgParaColorSeparator = 0x20
CfgParaTreeIgnoredLevel = 0x23
CfgParaTreeAutoFocus = 0x24
CfgParaPlxEnableAll = 0x25
CfgParaPlxEnabledList = 0x26
CfgParaPlxEnabledCategory = 0x27
CfgParaPlxPath = 0x28
CfgParaDisplayPicture = 0x29
CfgParaDeveloperMethod = 0x2a
CfgParaAppRestartInd = 0x2b
CfgParaIgnorePlxConfig = 0x2c
CfgParaTreeUseSimpleAsDefault = 0x2f
CfgParaTreeSimpleDispFormat = 0x30
CfgParaTreeSimplestDispFormat = 0x31

CfgParaLogObject = 0x80
CfgParaEntityObject = 0x81
CfgParaPlxObject = 0x82
CfgParaEscapeObject = 0x83
CfgParaConfigObject = 0x84
CfgParaResourceObject = 0x85
CfgParaHelpObject = 0x86
CfgParaEnvObject = 0x88

CfgParaCwd = 0x90
CfgParaConsole = 0x91
CfgParaPlatform = 0x93
CfgParaDefault = 0xff

id_Save_Node = wx.NewId()
id_Save_Binary = wx.NewId()
id_Save_Hex = wx.NewId()
id_OpenWithPlx = wx.NewId()
id_OpenWithSegment = wx.NewId()
id_OpenAsJson = wx.NewId()
id_DumpContent = wx.NewId()
id_Goto = wx.NewId()
id_FindPrev = wx.NewId()
id_FindNext = wx.NewId()
id_Copy = wx.NewId()
id_Copy_Subject = wx.NewId()
id_Copy_Description = wx.NewId()
id_Copy_Selection = wx.NewId()
id_AsciiTable = wx.NewId()
id_InstallPlx = wx.NewId()
id_RunPlx = wx.NewId()
id_RecentFile = wx.NewId()
id_PlxInfo = wx.NewId()
id_PlxTools = wx.NewId()
id_ShowConfig = wx.NewId()
id_ShowEnv = wx.NewId()

id_ExportWith = wx.NewId()
id_GenerateWith = wx.NewId()

id_SaveNode_Binary = wx.NewId()
id_SaveNode_Hex = wx.NewId()
id_Expand = wx.NewId()
id_ExpandAll = wx.NewId()
id_ExpandChildren = wx.NewId()
id_Collapse = wx.NewId()
id_CollapseAll = wx.NewId()

id_ExportTree = wx.NewId()
id_ExportNode = wx.NewId()
id_ExportWithLevel = wx.NewId()
id_ExportJson = wx.NewId()
id_ParseWith = wx.NewId()
id_ShoHelpContent = wx.NewId()


class Ids:
    WRAP_FUNC = {
        id_OpenWithSegment: ('Cmd_OpenWithSegment', 'Update_OpenWithSegment'),
        wx.ID_SAVE: ('Cmd_Save', 'Update_Save'),
        wx.ID_SAVEAS: ('Cmd_Saveas', 'Update_Saveas'),
        id_Save_Node: ('Cmd_SaveNode', 'Update_SaveNode'),
        id_Save_Binary: ('Cmd_SaveBinary', 'Update_Save'),
        id_Save_Hex: ('Cmd_SaveHex', 'Update_Save'),
        id_SaveNode_Binary: ('Cmd_SaveNode_Binary', 'Update_SaveNode'),
        id_SaveNode_Hex: ('Cmd_SaveNode_Hex', 'Update_SaveNode'),
        id_DumpContent: ('Cmd_DumpContent', 'Update_DumpContent'),
        wx.ID_FIND: ('Cmd_Find', 'Update_Find'),
        id_FindPrev: ('Cmd_FindPrevious', 'Update_FindPrevious'),
        id_FindNext: ('Cmd_FindNext', 'Update_FindNext'),
        id_Goto: ('Cmd_Goto', 'Update_Goto'),
        wx.ID_COPY: ('Cmd_Copy', 'Update_Copy'),
        id_Copy: ('Cmd_CopyItem', 'Update_CopyItem'),
        id_Copy_Subject: ('Cmd_CopyItem', 'Update_CopyItem'),
        id_Copy_Description: ('Cmd_CopyItem', 'Update_CopyItem'),
        id_Copy_Selection: ('Cmd_CopyItem', 'Update_CopyItem'),
        id_ExportWith: ('Cmd_ExportWith', 'Update_ExportWith'),
        id_GenerateWith: ('Cmd_CreateWith', 'Update_GenerateWith'),
        id_Expand: ('Cmd_Expand', 'Update_Expand'),
        id_ExpandAll: ('Cmd_ExpandAll', 'Update_ExpandAll'),
        id_ExpandChildren: ('Cmd_ExpandChildren', 'Update_ExpandChildren'),
        id_Collapse: ('Cmd_Collapse', 'Update_Collapse'),
        id_CollapseAll: ('Cmd_CollapseAll', 'Update_CollapseAll'),

        id_ExportNode: ('Cmd_ExportNode', 'Update_ExportNode'),
        id_ExportTree: ('Cmd_ExportTree', 'Update_ExportTree'),
        id_ExportWithLevel: ('Cmd_ExportWithLevel', 'Update_ExportWithLevel'),
        id_ExportJson: ('Cmd_ExportWithJson', 'Update_ExportWithJson'),
        id_ParseWith: ('Cmd_ParseWith', 'Update_ParseWith'),
        id_ShoHelpContent: ('Cmd_PlxHelpContent', 'Update_PlxHelpContent')
    }

    def __init__(self, app, ui, tryWrapper=None):
        self.app = app
        self.ui = ui
        if tryWrapper is None:
            self.tryWrapper = ab_exceptions.TryWrapperFactory(self, self.app)
        else:
            self.tryWrapper = tryWrapper

        self.plxIds = dict()
        self.creatorIds = dict()
        self._initDispatchMenus()

    def _update(self, ui, key, cmd_func, update_func):
        # add a prefix 'On' for event binds
        cmd_func, update_func = map(lambda f: 'On' + f,
                                    (cmd_func, update_func))
        if hasattr(ui, cmd_func):
            wx.EVT_MENU(ui, key, self.tryWrapper(getattr(ui, cmd_func)))
        if hasattr(ui, update_func):
            wx.EVT_UPDATE_UI(ui, key,
                             self.tryWrapper(getattr(ui, update_func)))

    def _initDispatchMenus(self):
        for key, (cmd_func, update_func) in self.WRAP_FUNC.items():
            self._update(self.ui, key, cmd_func, update_func)

        self._loadParsedWithIds()

    def _loadParsedWithIds(self):
        plx = self.app.readKey(CfgParaPlxObject)

        # duplicate the functions of id_ParseWith
        cmd_pfunc, update_pfunc = self.WRAP_FUNC[id_ParseWith]
        cmd_efunc, update_efunc = self.WRAP_FUNC[id_ExportWith]
        for p in plx.getPlxList(required_all=True):
            self.plxIds[p] = list()
            self.plxIds[p].append(wx.NewId())
            self._update(self.ui, self.plxIds[p][-1], cmd_pfunc, update_pfunc)
            self.plxIds[p].append(wx.NewId())
            self._update(self.ui, self.plxIds[p][-1], cmd_efunc, update_efunc)

    def getParsedIdWithPlx(self, plx):
        return self.plxIds.get(plx, (-1, -1))[0]

    def getParsedPlxWithId(self, key):
        for plx, value in self.plxIds.items():
            if value[0] == key:
                return plx

        return None

    def getExportedIdWithPlx(self, plx):
        return self.plxIds.get(plx, (-1, -1))[1]

    def getExportedPlxWithId(self, key):
        for plx, value in self.plxIds.items():
            if value[1] == key:
                return plx

        return None

    def getCreatorIdWithPlx(self, plx, interface=None):
        if plx in self.creatorIds:
            if interface in self.creatorIds[plx]:
                return self.creatorIds[plx][interface]
        else:
            self.creatorIds[plx] = dict()

        key = wx.NewId()
        self.creatorIds[plx][interface] = key

        cmd_gfunc, update_gfunc = self.WRAP_FUNC[id_GenerateWith]
        self._update(self.ui, key, cmd_gfunc, update_gfunc)
        return key

    def getCreatorPlxWithId(self, key):
        for plx, ids in self.creatorIds.items():
            for interface, i in ids.items():
                if i == key:
                    return plx, interface

        return None, None

    def dispatchParentMenus(self, ui):
        for func_list in self.WRAP_FUNC.values():
            cmd_func, update_func = func_list
            if hasattr(ui, cmd_func):
                ui.parent.__dict__[cmd_func] = getattr(ui, cmd_func)
            if hasattr(ui, update_func):
                ui.parent.__dict__[update_func] = getattr(ui, update_func)
